<?php
declare(strict_types=1);

namespace SixShop\ShippingTemplate\Entity;

use SixShop\Core\Entity\BaseEntity;
use SixShop\ShippingTemplate\Model\ShippingTemplateRuleModel;

/**
 * @mixin ShippingTemplateRuleModel
 */
class ShippingTemplateRuleEntity extends BaseEntity
{
    /**
     * 根据模板ID获取默认规则
     */
    public function getDefaultRule(int $templateId): ?ShippingTemplateRuleModel
    {
        return $this->where('template_id', $templateId)
            ->where('area_type', 'default')
            ->find();
    }

    /**
     * 根据模板ID获取特殊区域规则
     */
    public function getSpecialRules(int $templateId): iterable
    {
        return $this->where('template_id', $templateId)
            ->where('area_type', 'special')
            ->select();
    }

    /**
     * 计算运费
     */
    public function calculateShippingFee(float $quantity, ?string $regionCode = null): float
    {
        // 获取模板ID
        $templateId = $this->template_id;
        
        // 查找适用的规则
        $rule = null;
        
        // 如果提供了地区编码，先检查是否匹配特殊区域规则
        if ($regionCode) {
            $specialRules = $this->getSpecialRules($templateId);
            foreach ($specialRules as $specialRule) {
                $regions = json_decode($specialRule->regions, true);
                if (is_array($regions) && in_array($regionCode, $regions)) {
                    $rule = $specialRule;
                    break;
                }
            }
        }
        
        // 如果没有匹配的特殊区域规则，则使用默认规则
        if (!$rule) {
            $rule = $this->getDefaultRule($templateId);
        }
        
        // 如果没有找到任何规则，返回0
        if (!$rule) {
            return 0.0;
        }
        
        // 计算运费
        if ($quantity <= $rule->first) {
            // 数量在首件/首重/首体积范围内
            return (float)$rule->first_price;
        } else {
            // 超出部分按续件/续重/续体积计费
            $excess = $quantity - $rule->first;
            // 简化计算，实际项目中可能需要考虑向上取整等规则
            $additionalFee = ceil($excess) * (float)$rule->next_price;
            return (float)$rule->first_price + $additionalFee;
        }
    }
}